Hello,大家好,我是Bing,在新工作接觸到RxSwift,過程中受到我學長許多幫忙,也接觸到許多大神的教材,期許接下來30天,能從頭了解RxSwift,一方面精進一方面分享,若有大神路過,請多多指導一下!
關於這30天的規劃,起初會花點時間讚揚Rx跟介紹資源,接著圍繞著Observable的各種操作,預計約會花了兩週時間,因為剛開始在使用Rx時都會胡亂用,想趁這個機會仔細地理解它們,所以才叫做探索之旅(笑)
接著,花約略一週時間討論異常處理、多執行緒、測試,最後一週,討論UITableView+Rx、常用的RxSwift套件,有機會的話想帶個練習當作最後ending,不知道時間夠不夠用,就邊走邊看吧!
好了,第一天不能偷懶,以下開始正文
RxSwift最被大家喜愛的原因應該是binding神好用,但RxSwift不只有binding哦,我覺得重點在它的Functional特性,帶給我們撰寫思維改變,還有Reactive特性能輕易解決非同步問題。
RxSwift就是ReactiveX的Swift版本,所以我們先從ReactiveX(簡稱Rx)官方首頁看起,看看是怎麼解釋Rx,有這麼一句話
ReactiveX is a combination of the best ideas from
the Observer pattern, the Iterator pattern, and functional programming
這裡面有三個專有名詞,每個都是很艱深的知識,今天我們就圍繞著這三個專有名詞,概略的了解一下Rx吧!
是設計模式的一種,概念是這樣,會有一個被觀察者(Observable)和多個觀察者(Observer),當Observable改變狀態,Observer就能收到通知,也就是說Observer不用一直去檢查Observable的狀態。
當在一對多物件之間要溝通時,觀察者模式就特別好用,另外,Observer是基於Observable的介面,所以對Observable來說,它不知道Observer的實作細節,也就代表兩者之間是鬆耦合(loose-coupling),所以可以輕易的加入或移除Observer,程式還是會運行的很順暢。
在Rx當中,就是以觀察者模式為基礎,來監聽Observable streams的變化,並且發送給Observer。
是設計模式的一種,多個物件聚集起來成為一個聚合(Collection),可能是Array、Stack或是ArrayList...等,不同的資料結構取值的方法都不同。
疊代器模式會有一個名為Iterator的介面,基本上有兩個method,next
跟hasNext
,不同的資料結構去實踐 Iterator的介面,在藉由Iterator.next
來發送數值給使用者,這樣用起來就會很舒服,根本不用在乎裡面的實作方式,也是一種基於介面不基於實作的例子。
在Rx當中,Observable就像是Iterator一樣,依序的來發送元素給訂閱他的訂閱者,也就是Rx中的.next事件,若發送完畢,就會發送.completed事件,也就是對應Iterator中的!hasNext()。
程式設計法是定義程式風格的一門學問,在介紹Functional programming之前,因為我覺得這很有趣,所以讓我們先花點時間了解Imperative programming(指令式程式設計)跟Declarative programming(宣告式程式設計),下面我就簡稱 Imperative 跟 Declarative。
撰寫Imperative大概會像下面這樣,工程師去命令電腦該如何去做(How to do),程式碼基本上就是從上往下跑,整體來說是線性,並且會保留狀態(state),狀態會保存一些數值,在各種情境下根據狀態來決定程式走向,並且隨著時間不同,狀態會跟著改變,這種你做了某些事情,導致某個地方改變了(可能狀態改變、可能寫資料到硬碟等等),這就是所謂的Side effect(副作用)。
var maleCount = 0, femaleCount = 0;
for student in students {
if (student.gender == "M") {
maleCount += 1
} else {
femaleCount += 1
}
}
根據Peter Van Roy 的所提出的程式設計法分類,有統整一張分類圖,可以看到Object-oriented programming(物件導向程式設計,簡稱OOP)就是指令式衍伸的一種。
另一種是Declarative,SQL就是其中一種,撰寫的時候很像是用描述的方式在寫程式,告訴電腦我要做什麼(What to do),你要怎麼處理我都不在意,給我結果就好,在可讀性上很好,通常照著順序瀏覽就能理解程式的目的Functional programming就是屬於Declarative的一種。
SELECT count(*) FROM Student WHERE gender = 'M';
SELECT count(*) FROM Student WHERE gender = 'F';
在找素材時,看到這影片 GOTO 2017 • Programming Across Paradigms • Anjana Vakil,講者Anjana Vakil全面性的介紹程式設計法,淺顯易懂,小弟我受益良多,下面擷取部分內容跟我自己的心得。
隨著專案越來越大,Imperative的方式會充斥著各種State,就好像精密的時鐘,可能程式擺的順序不同,導致在某個時間點的狀態不同,最終,對結果照成非預期影響,重點你要Debug還很難,這就是為什麼Global variable 很可怕,這也點出一個點,因為變數是Mutable(可變的),在運行時所以會很難確切掌握。
面對這問題,有人提出OOP,大致上概念就是把程式切小塊,彼此之間不共享狀態(Share state),減少狀態被莫名其妙被其他程式改變的問題,但仍然允許Mutable state。
另一種解決方法,就是Functional programming,它就像生產線一樣,資料的方向是單一的,寫起來會像串香腸一樣,一個串一個。它極力避免Mutable state,也就是倡導Immutable(不可變的),實際上就是把程式碼變成 Pure function,講白話就是,你給它input,Pure function會幫你處理一些事情,做完會給你output,全部事情就在function內部做完,且不會影響到外部其他狀態,稱為『沒有side effect』。Functional programming來寫大概會像這樣
let femaleCount = students.filter { $0.gender == "F" }.count
let maleCount = students.filter { $0.gender == "M" }.count
經過上面出淺的介紹,可以理解Rx就是 Observer pattern + Iterator pattern + Functional programming,Rx基於可觀察的Observable構成一個非同步(asynchronous)與事件為主(event-based)的程式,是Reactive Programming(回應式程式設計)的一種實現方式,所謂的Reactive Programming就是 data streams的概念,事件、消息、錯誤訊息...等一切的一切將透過Data streams傳遞,藉由觀察這些stream來作出對應的反應,且一切都是以非同步的方式進行。
在找資料的過程中,看到有人說Rx是Functional Reactive Programing(FRP),在官方介紹中有特別說明,這不是那麼正確,Rx可能會是Functional,可能會是Reactive,但FRP是另外一件東西,在定義的上 FRP 則是隨著時間continuously(連續的)操作數值,Rx則是 discrete(離散的)
如講者 Anjana Vakil 在影片中講的,我們要做的不是說Functional programming好讚就都用,然後撇除 OOP,而是知道熟知兩者的優缺點,在面對不同情境下,選擇出最合適的方案,如同我們使用Rx,不應該不加思索的使用,有些靜態的、固定的,也許就可以衡量是不是用原生的做法就好?這樣也許更加單純好維護。
第一天好像講太多,因為自己也滿有興趣,找了一些資料,放心,從明天開始,篇幅不會這麼多了(?),明天講講怎麼自學,有哪些推薦資源,就這樣,明天見。